package action;

import org.hibernate.Session;
import org.hibernate.SessionFactory;

import bean.Role;
import dao.RoleDao;
import dao.UserDao;
import util.HibernateUtil;

/**
 * Hibernate中的Session的事务管理
 * 
 * @author 半颗柠檬、
 * 
 */
public class Hibernate_Session {
	public static void main(String[] args) {
		// Hibernate_Session.testone();

		// Hibernate_Session.testTwo();

		// Hibernate_Session.testThree();

		Hibernate_Session.testFour();
	}

	private static void testone() {

		/**
		 * 每次由sessionFactory。openSession()得到的session都不一样，
		 */
		SessionFactory sessionFactory = HibernateUtil.getSessionFactory();

		Session session1 = sessionFactory.openSession();
		System.out.println(session1.hashCode());

		Session session2 = sessionFactory.openSession();
		System.out.println(session2.hashCode());

		/*
		 * UserDao和RoleDao中的save1方法的session都是通过sessionFactory.openSession()所得到，
		 * 不是同一个session，也就是说两个方法不是公用一个事务
		 */
		UserDao.save1();
		RoleDao.save1();

	}

	private static void testTwo() {

		/**
		 * 由HibernateUtil.getSession()得到的是同一个session对象，查看HibernateUtil。
		 * getSession()可知getSession方法是从ThreadLocal中取得的。
		 */
		Session session1 = HibernateUtil.getSession();
		System.out.println(session1.hashCode());

		Session session2 = HibernateUtil.getSession();
		System.out.println(session2.hashCode());

		/**
		 * 虽然UserDao和RoleDao中是同一个session，但是两个方法却不是同一个事务，因为每一个方法里的tran.commit（）
		 * 方法都隐式调用了flush方法，这个方法
		 * 的主要作用是清理缓存，强制数据库与Hibernate缓存同步，以保证数据的一致性，然后再提交事务，UserDao.save2()方法
		 * 已经提交事务，等到RoleDao.save2()方法的时候， 事务已经是新的了。
		 */
		UserDao.save2();
		RoleDao.save2();

	}

	/**
	 * 使用getCurrentSession时， 在hibernate.cfg.xml中要配置
	 * 
	 * <property name="current_session_context_class">thread</property>
	 * 这个配置的目的是把session交给ThreadLocal管理
	 * 
	 * getCurrentSession时，Session会自动关闭。不需要手工关闭。
	 */
	private static void testThree() {

		/**
		 * 使用getSessionFactory().getCurrentSession()得到的session是同一个线程上的同一个session
		 * getSessionFactory().
		 * getCurrentSession创建的线程会在事务回滚或事物提交后自动关闭，如果手动关闭则会报错。
		 */
		Session session1 = HibernateUtil.getSessionFactory()
				.getCurrentSession();
		System.out.println(session1.hashCode());

		Session session2 = HibernateUtil.getSessionFactory()
				.getCurrentSession();
		System.out.println(session2.hashCode());

		/**
		 * 两个方法依然无法共享一个事务，值得注意的是这两个方法的session不是同一个session，
		 * 原因在于getCurrentSession的session会在事务回滚或者提交之后自动关闭
		 * ，当UserDao.save3()成功提交之后session就关闭了，所以RoelDao的session是重新创建的 session
		 */
		UserDao.save3();
		RoleDao.save3();

	}

	private static void testFour() {

		Session session = HibernateUtil.getSessionFactory().getCurrentSession();

		/**
		 * UserDao和RoleDao的save4方法共享一个session
		 * 但是依旧无法共享事务,因为session在UserDao.save4方法提交的时候已经被关闭了，
		 * RoleDao.save4使用session就会报错，错误消息为“Session is closed!”
		 */
		UserDao.save4(session);
		RoleDao.save4(session);

	}

}
